package com.qdlc.p2p.biz.service.user;

import java.io.File;
import java.io.Serializable;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.jcraft.jsch.SftpException;
import com.qd.p2p.sina.pay.bussniessparam.AuditMemberInfosParam;
import com.qd.p2p.sina.pay.enums.BankCode;
import com.qd.p2p.sina.pay.enums.MemberType;
import com.qd.p2p.sina.pay.response.BlankResponse;
import com.qd.p2p.sina.pay.response.CreateActivateMemberResponse;
import com.qd.p2p.sina.service.SinaPayService;
import com.qdlc.p2p.biz.service.MemberInfosService;
import com.qdlc.p2p.biz.service.UserIdentifyService;
import com.qdlc.p2p.biz.service.UserService;
import com.qdlc.p2p.biz.util.NotifyRequestUrl;
import com.qdlc.p2p.biz.util.SinaSftp;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.core.redis.JedisCacheFactory;
import com.qdlc.p2p.common.exception.UserException;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.OrderNoUtil;
import com.qdlc.p2p.common.util.SinaRSA;
import com.qdlc.p2p.common.util.SinaTools;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dao.MemberInfosDao;
import com.qdlc.p2p.dal.dto.MemberInfos;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserIdentify;
import com.qdlc.p2p.dal.util.UserTypeUtils;
import com.qdlc.p2p.dal.util.UserUtils;

/**
 * 企业帐户开户
 *
 * @author linya
 */
@Service
public class UserMemberRealNameServiceImpl implements UserMemberRealNameService {

	private static final String USER_MEMBER_REAL_NAME_STEP_KEY = "user_member_real_name_step_";

	private static final int STEP_STATUS_0 = 0;

	private static final int STEP_STATUS_1 = 1;

	private static final int STEP_STATUS_2 = 2;

	private static final int STEP_STATUS_3 = 3;

	@Resource
	UserService userService;

	@Resource
	UserIdentifyService userIdentifyService;

	@Resource
	MemberInfosService memberInfosService;

	@Resource
	SinaPayService sinaPayService;

	@Resource
	MemberInfosDao memberInfosDao;

	@Override
	public ReturnResult realName(User user, MemberInfos member) {

		long userId = user.getUserId();

		// 检测前置条件
		ReturnResult result = preCheckRealName(userId, member);
		if (result.isError()) {
			return result;
		}

		MemberInfos dbMemberInfos = (MemberInfos) result.getExtra("member");

		MemberInfosStepModel stepModel = getStep(userId, member);

		// 第一步: 获取第三方ID, 如果没有获取，则进行开户处理
		if (stepModel.getStatus() == STEP_STATUS_0) {
			result = step0(user, stepModel);
		}

		// 上传图片路径
		if (stepModel.getStatus() == STEP_STATUS_1) {
			result = step1(member.getFilePath(), stepModel);
		}

		// 请求审核企业会员
		if (stepModel.getStatus() == STEP_STATUS_2) {
			result = step2(stepModel);
		}

		// 保存开户信息到数据库中
		if (stepModel.getStatus() == STEP_STATUS_3) {
			try {
				member.setId(dbMemberInfos.getId());
				saveMemberInfos(user, member);
				incrementStep(stepModel);
			} catch (Exception e) {
				result = new ReturnResult("保存开户信息出现错误,请重试!");
			}
		}

		if (result.isError()) {
			putStep(user.getUserId(), stepModel);
		} else {
			cleanStep(user);
		}

		return result;
	}

	/**
	 * 企业开户
	 *
	 * @param user
	 * @return
	 */
	private ReturnResult step0(User user, MemberInfosStepModel stepModel) {
		String tppUserCustId = UserUtils.getUserTppCustId(user.getUserId());
		if (StringUtils.isBlank(tppUserCustId)) {
			tppUserCustId = OrderNoUtil.getInstance().getSerialNumber();
			CreateActivateMemberResponse response = sinaPayService.createActiveMember(tppUserCustId,
					MemberType.company);
			if (!response.success()) {
				return new ReturnResult("开户失败!");
			}
		}
		incrementStep(stepModel);
		stepModel.getMember().setIdentityId(tppUserCustId);
		return ReturnResult.SUCCESS;
	}

	/**
	 * 上传图片路径
	 *
	 * @param filePath
	 * @return
	 */
	private ReturnResult step1(String filePath, MemberInfosStepModel stepModel) {
		try {
			SinaSftp s = new SinaSftp();
			s.upload("/upload/", filePath, s.connectSFTP());
			s.ls("/upload/", s.connectSFTP());
			incrementStep(stepModel);
		} catch (SftpException e) {
			return new ReturnResult("企业资质文件有误!");
		}
		return ReturnResult.SUCCESS;
	}

	/**
	 * 请求审核企业会员
	 *
	 * @param stepModel
	 * @return
	 */
	private ReturnResult step2(MemberInfosStepModel stepModel) {
		AuditMemberInfosParam param = populateRequestParam(stepModel.getMember());
		BlankResponse response = sinaPayService.auditMemberInfos(param);
		if (response.success()) {
			incrementStep(stepModel);
		} else {
			return new ReturnResult("新浪企业开户失败!");
		}
		return ReturnResult.SUCCESS;
	}

	private void putStep(long userId, MemberInfosStepModel stepModel) {
		JedisCacheFactory.newInstance(MemberInfosStepModel.class).set(USER_MEMBER_REAL_NAME_STEP_KEY + userId,
				stepModel, 1, TimeUnit.HOURS);
	}

	private MemberInfosStepModel getStep(long userId, MemberInfos member) {
		MemberInfosStepModel stepModel = JedisCacheFactory.newInstance(MemberInfosStepModel.class)
				.get(USER_MEMBER_REAL_NAME_STEP_KEY + userId);
		if (stepModel == null) {
			stepModel = new MemberInfosStepModel(0, member);
		}
		return stepModel;
	}

	private void cleanStep(User user) {
		JedisCacheFactory.newInstance(MemberInfosStepModel.class)
				.delete(USER_MEMBER_REAL_NAME_STEP_KEY + user.getUserId());
	}

	private void incrementStep(MemberInfosStepModel stepModel) {
		stepModel.setStatus(stepModel.getStatus() + 1);
	}

	/**
	 * 检测前置条件:
	 * 1. 检测是否是公司帐号
	 * 2. 检测是否已经实名认证
	 * 3. 检测Member状态是否已经处理认证中
	 *
	 * @param userId
	 * @return
	 */
	private ReturnResult preCheckRealName(long userId, MemberInfos member) {

		// 检测是否是公司帐号
		if (!UserTypeUtils.isCorporate(userId)) {
			throw new UserException("您不是企业用户，不能进行企业开户！", 1);
		}

		// 检测是否已经实名认证
		UserIdentify userIdentify = userIdentifyService.findByUserId(userId);
		if (userIdentify.getRealNameStatus() == 1) {
			return new ReturnResult("您已开户，请勿重复开户!");
		}

		// 检测Member已存在的状态
		MemberInfos dbMember = memberInfosService.findByUserId(userId);
		if (dbMember.getStatus() == 99) {
			return new ReturnResult("您的企业开户请求新浪已受理，请等待!");
		}

		// 检测法人存在性
		boolean exsit = memberInfosDao.exsitLegalPerson(member.getLegalPerson());
		if (exsit) {
			return new ReturnResult("企业法人已经被使用!");
		}

		exsit = memberInfosDao.exsitCertNo(member.getCertNo());
		if (exsit) {
			return new ReturnResult("企业法人身份证号码已经被使用!");
		}

		exsit = memberInfosDao.exsitLegalPersonPhone(member.getLegalPersonPhone());
		if (exsit) {
			return new ReturnResult("企业法人手机号已经被使用!");
		}

		ReturnResult result = new ReturnResult();
		result.addExtra("member", dbMember);

		return result;
	}

	@Override
	public void saveMemberInfos(User user, MemberInfos member) {
		// 申请提交成功，新浪审核中
		MemberInfos m = memberInfosDao.findByUserId(member.getUserId());
		member.setStatus((byte) 99);
		if (m == null) {
			memberInfosDao.save(member);
		} else {
			member.setId(m.getId());
			memberInfosDao.update(member);
		}
		// 保存用户信息
		userService.update(user);
	}

	@Override
	public void updateStatusByTppId(int status, String msg, String tppId) {
		MemberInfos member = memberInfosService.findByIdentityId(tppId);
		if (member != null) {
			try {
				// 更新用户实名状态
				userIdentifyService.modifyRealnameStatus(member.getUserId(), 1, 0);
				member.setAuditMessage(msg);
				member.setStatus((byte) status);
				// 申请提交成功，新浪审核中
				memberInfosDao.update(member);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 构建审核企业会员的请求参数
	 *
	 * @param member
	 * @return
	 */
	private AuditMemberInfosParam populateRequestParam(MemberInfos member) {
		AuditMemberInfosParam param = new AuditMemberInfosParam();
		String publicKey = SystemConfigHelper.getValue(Nid.CON_ENCRYPT);
		param.setAuditOrderNo(OrderNoUtil.getInstance().getSerialNumber());
		param.setIdentityId(member.getIdentityId());
		param.setCompanyName(member.getCompanyName());
		param.setWebsite(member.getWebsite());
		param.setAddress(member.getAddress());
		param.setLicenseNo(SinaRSA.encryptByPublicKey(member.getLicenseNo(), publicKey));
		param.setLicenseAddress(member.getLicenseAddress());
		param.setLicenseExpireDate(DateUtil.dateStr7(member.getLicenseExpireDate()));
		param.setBusinessScope(member.getBusinessScope());
		param.setTelephone(SinaRSA.encryptByPublicKey(member.getTelephone(), publicKey));
		param.setEmail(SinaRSA.encryptByPublicKey(member.getEmail(), publicKey));
		param.setOrganizationNo(SinaRSA.encryptByPublicKey(member.getOrganizationNo(), publicKey));
		param.setLegalPerson(SinaRSA.encryptByPublicKey(member.getLegalPerson(), publicKey));
		param.setLegalPersonPhone(SinaRSA.encryptByPublicKey(member.getLegalPersonPhone(), publicKey));
		param.setSummary(member.getSummary());
		param.setCertNo(SinaRSA.encryptByPublicKey(member.getCertNo(), publicKey));
		param.setBankCode(BankCode.getByCode(member.getBankCode()));
		param.setBankAccountNo(SinaRSA.encryptByPublicKey(member.getBankAccountNo(), publicKey));
		param.setBankBranch(member.getBankBranch());
		param.setProvince(member.getProvince());
		param.setCity(member.getCity());
		param.setFileName(member.getFileName());
		param.setDigestType(member.getDigestType());
		param.setNotifyUrl(NotifyRequestUrl.AUDIT_MEMBERINFOS_NOTIFY_URL);

		// 文件路劲
		String file_path = SystemConfigHelper.getValue(Nid.COMPANY_FILE_PATH) + member.getFilePath();
		File file = new File(file_path);
		String filemd5 = SinaTools.getFileMD5(file);
		String digest = filemd5;// 文件摘要
		param.setDigest(digest);
		return param;
	}

	private class MemberInfosStepModel implements Serializable {
		int status;
		MemberInfos member;

		public MemberInfosStepModel(int status, MemberInfos member) {
			this.status = status;
			this.member = member;
		}

		public int getStatus() {
			return status;
		}

		public void setStatus(int status) {
			this.status = status;
		}

		public MemberInfos getMember() {
			return member;
		}

		public void setMember(MemberInfos member) {
			this.member = member;
		}
	}
}
